# -*- coding:utf-8 -*-
import json
import os
import re
import time
import urllib
import pymysql
import requests
from .celery import app
from api.models import Apis, Apistep, Apitest
from set.models import Set
from bug.models import Bug as bug
from django.utils.html import format_html


def PATH(p):
    return os.path.abspath(os.path.join(os.path.dirname(__file__), p))


global driver


@app.task
def hello_world():
    print('已运行')


@app.task(bind=True)
def debug_task(self):
    print('Request: {0!r}'.format(self.request))


@app.task
def apisauto_testcase(self):
    """
    @description: 单接口测试用例的入口，目前没有添加执行条件，会把所有的单接口测试用例依次执行
    @param {type}
    @return: 无返回值
    """
    # 获取所有测试用例，后期可以加上是否有效的条件
    info = list(Apitest.objects.filter().values())
    interfaceTest1(info)



def interfaceTest1(case_list):
    """
    @description: 单接口测试用例执行
    @case_list {type：list} ：测试用例列表，列表元素为字典，
        如：[{"":"","":"","":""},
            {"":"","":"","":""},
            {"":"","":"","":""}]
    @return: 返回执行结果，type：dict。如：{"":"","":"","":""}
    """
    # res_flags = []
    request_urls = []
    # responses = []
    strinfo = re.compile('{HOSTNAME}')
    for case in case_list:
        try:
            case_id = case['id']
            interface_name = case['apiname']
            method = case['apimethod']
            url = case['apiurl']
            param = case['apiparamvalue']
            res_check = case['apiresult']
            product = case['Product_id']
        except Exception as e:
            return {'code': 'Fail', 'msg': '测试用例格式不正确！%s'} % e
        if param == '':
            new_url = 'http://' + url
        elif param == 'null':
            url = strinfo.sub(str(seturl('HOSTNAME')), url)
            new_url = 'http://' + url
        else:
            a = str(seturl('HOSTNAME'))
            print("a:", a)
            url = strinfo.sub(a, url)
            new_url = 'http://' + url
            request_urls.append(new_url)
        if method.upper() == "POST":
            print("我在执行POST方法！！！！！！！！！！！！！")
            headers = {'Authorization': '', 'Content-Type': 'application/json'}
            if "=" in urlParam(param):
                data = None
                try:
                    # 调用接口，并记录测试结果，获取的结果为json格式，需转换为str
                    # 采用url方式调用
                    results = str(requests.post(new_url + '?' + urlParam(param),
                                                data,
                                                headers=headers).json())
                except Exception as e:
                    print("我出错了！！！")
                    return caseWriteResult1(case_id, str(e), '0')
            else:
                print(' request  is POST2 ' + new_url + '   body is ' +
                      urlParam(param))
                data = param
                try:
                    results = str(requests.post(new_url, data, headers).json())
                except Exception as e:
                    print("我出错了！！！")
                    return caseWriteResult1(case_id, str(e), '0')
        if method.upper() == 'GET':
            headers = {'Authorization': '', 'Content-Type': 'application/json'}
            if "=" in urlParam(param):
                data = None
                print(
                    str(case_id) + ' request  is get' +
                    new_url + '?' +
                    urlParam(param))
                results = requests.get(new_url + '?' + urlParam(param),
                                       data,
                                       headers=headers).text
                print('   response is get' + results)
            else:
                print(' request  is get ' + new_url + '   body is ' +
                      urlParam(param))
                data = None
                req = urllib.request.Request(url=new_url,
                                             data=data,
                                             headers=headers,
                                             method="GET")
                try:
                    results = urllib.request.urlopen(req).read()
                    print('   response is get1 ')
                    print(results)
                except Exception as e:
                    return caseWriteResult1(case_id, str(e), '0')

        if method.upper() == 'PUT':
            headers = {
                'Host': 'HOSTNAME',
                'Connection': 'keep-alive',
                'CredentialId': id,
                'Content-Type': 'application/json'
            }
            body_data = param
            results = requests.put(url=url, data=body_data, headers=headers)
            # responses.append(results)
            # res = readRes(results, res_check)
            # if 'pass' == res:
            #     #         writeResult(case_id,'pass')
            #     res_flags.append('pass')
            # else:
            #     res_flags.append('fail')
            #     #     writeResult(case_id,'fail')
            #     writeBug(case_id, product, interface_name, new_url, results,
            #              res_check)
        if method.upper() == "PATCH":
            headers = {
                'Authorization': 'Credential ' + id,
                'Content-Type': 'application/json'
            }
            data = None
            results = str(requests.patch(new_url + '?' + urlParam(param),
                                         data,
                                         headers=headers).json)

        res = readRes(results, res_check)
        # res = json.loads(res)
        # print('res_ytpe:',res['code'])
        if 'pass' == res['code']:
            caseWriteResult1(case_id, results, '1')
        else:
            caseWriteResult1(case_id, results, '0')
            print("发现bug，开始写bug：", interface_name)
            writeBug(case_id, product, interface_name, new_url,
                     results, res_check)
    return res


def readRes(result, res_check):
    """
        进行字符串比对，判断测试结果和预期是否一致
        比对是按照字符串查找方式进行不对，找到指定的字符串即为通过
        res:字符串格式，非字典格式

    """
    # print("res:", res)
    # print("res_check:", res_check)
    result = result.replace('":"', "=").replace('":', "=")
    res_check = res_check.split(';')
    for s in res_check:
        if s in result:
            resultPass = {"code": "pass", "msg": "测试通过！"}
            return resultPass
        else:
            result="{"+str(result)+"}"
            # res_check="{"+str(res_check)+"}"
            print("====++++====:",result)
            msg = format_html(
                "<td>错误，返回参数和预期结果不一致</td><br/>\
                <td>预期结果为：'{}'</td><br/>\
                <td>实际结果为：'{}'</td><br/>"                                                                                                                                                                                                                                                                                               .format(res_check, res))
            print("我一定要找到你：",msg)
            resultFail = {'code': 'Fail', 'msg': msg}
            return resultFail


def urlParam(param):
    param1 = param.replace('&quot;', '"')
    return param1


def CredentialId():
    global id
    url = 'http://' + 'api.test.com.cn' +\
        '/api/Security/Authentication/Signin/web'
    body_data = json.dumps({"Identity": 'test', "Password": 'test'})
    headers = {'Connection': 'keep-alive', 'Content-Type': 'application/json'}
    response = requests.post(url=url, data=body_data, headers=headers)
    data = response.text
    regx = '.*"CredentialId":"(.*)","Scene"'
    pm = re.search(regx, data)
    id = pm.group(1)


def caseWriteResult1(case_id, response, result):
    """
    更新用例的执行状态，并记录实际返回结果
    case_id：传入测试用例的id，int类型
    response：请求的内容，str类型
    result：请求的内容，str类型
    """
    now = time.strftime("%Y-%m-%d %H:%M:%S")
    Apis.objects.filter(id=case_id).update(
        apiresponse=response, apistatus=result, create_time=now)


def writeBug(bug_id, product_id, interface_name, request, response, res_check):
    """
    记录测试bug
    bug_id：传入测试用例的id，int类型
    product_id：用例关联产品的id，int类型
    interface_name：用例接口的名称，str类型
    request：请求的内容，str类型
    response：请求的内容，str类型
    res_check：请求的内容，str类型
    """
    now = time.strftime("%Y-%m-%d %H:%M:%S")
    print("BUG_id type:", type(bug_id))
    print("interface_name:", interface_name)
    bugname = str(bug_id) + '_' + interface_name + '_出错了'
    bugdetail = '[请求数据]<br />' + request +\
        '<br/>' + '[预期结果]<br/>' + res_check +\
        '<br/>' + '<br/>' + '[响应数据]<br />' + '<br/>' + response

    bug.objects.create(bugname=bugname,
                       Product_id=product_id,
                       bugdetail=bugdetail,
                       bugstatus='激活',
                       buglevel='3',
                       bugcreater='seawave',
                       bugassign='seawave',
                       created_time=now)
    print("BUG已经生成！！！")


@app.task
def apitest_testcase():
    sql = "SELECT id,`apiname`,apiurl,apimethod,\
    apiparamvalue,apiresult,`apistatus` \
    from apitest_apistep where apitest_apistep.Apitest_id=2 "

    coon = pymysql.connect(user='root',
                           passwd='A2T4PrrJ3yM',
                           db='autotestplat',
                           port=3306,
                           host='127.0.0.1',
                           charset='utf8')
    cursor = coon.cursor()
    aa = cursor.execute(sql)
    info = cursor.fetchmany(aa)
    print(info)
    for ii in info:
        case_list = []
        case_list.append(ii)
        #   CredentialId()
        interfaceTest(case_list)
    coon.commit()
    cursor.close()
    coon.close()


def interfaceTest(case_list):
    res_flags = []
    request_urls = []
    responses = []
    strinfo = re.compile('{seturl}')
    tasknoinfo = re.compile('{taskno}')

    for case in case_list:

        try:
            case_id = case.id
            interface_name = case.apiname
            method = case.apimethod
            url = case.apiurl
            param = case.apiparamvalue
            res_check = case.apiresult
        except Exception as e:
            return '测试用例格式不正确！%s' % e
        if param == '':
            new_url = 'http://' + 'api.test.com.cn' + url
        elif param == 'null':
            url = strinfo.sub(str(seturl('HOSTNAME')), url)
            new_url = 'http://' + url
        else:
            url = strinfo.sub(str(seturl('HOSTNAME')), url)
            param = strinfo.sub(TaskId, param)
            param = tasknoinfo.sub(taskno, param)
            new_url = 'http://' + url
            request_urls.append(new_url)
        if method.upper() == 'GET':
            headers = {'Authorization': '', 'Content-Type': 'application/json'}
            if "=" in urlParam(param):
                data = None
                print(
                    str(case_id) + ' request  is get' +
                    new_url.encode('utf-8') + '?' +
                    urlParam(param).encode('utf-8'))
                results = requests.get(new_url + '?' + urlParam(param),
                                       data,
                                       headers=headers).text
                print('   response is get' + results.encode('utf-8'))
                responses.append(results)
                res = readRes(results, '')
            else:
                print(' request  is get ' + new_url + '   body is ' +
                      urlParam(param))
                data = None
                req = urllib.request.Request(url=new_url,
                                             data=data,
                                             headers=headers,
                                             method="GET")
                results = urllib.request.urlopen(req).read()
                print('   response is get ')
                print(results)
                res = readRes(results, res_check)
                if 'pass' == res:
                    res_flags.append('pass')
                    writeResult(case_id, results, '1')
                    caseWriteResult(case_id, '1')
                else:
                    res_flags.append('fail')
                    writeResult(case_id, results, '0')
                    caseWriteResult(case_id, '0')
                    writeBug(case_id, product_id, interface_name, new_url,
                             results, res_check)
        if method.upper() == 'PUT':
            headers = {
                'Host': HOSTNAME,
                'Connection': 'keep-alive',
                'CredentialId': id,
                'Content-Type': 'application/json'
            }
            body_data = param
            results = requests.put(url=url, data=body_data, headers=headers)
            responses.append(results)
            res = readRes(results, res_check)
            if 'pass' == res:
                writeResult(case_id, '', 'pass')
                res_flags.append('pass')
            else:
                res_flags.append('fail')
                writeResult(case_id, '', 'fail')
                writeBug(case_id, product_id, interface_name, new_url, results,
                         res_check)
            try:
                preOrderSN(results)
            except:
                print('ok')
        if method.upper() == "PATCH":
            headers = {
                'Authorization': 'Credential ' + id,
                'Content-Type': 'application/json'
            }
            data = None
            results = requests.patch(new_url + '?' + urlParam(param),
                                     data,
                                     headers=headers).text
            responses.append(results)
            res = readRes(results, res_check)
            if 'pass' == res:
                writeResult(case_id, '', 'pass')
                res_flags.append('pass')
            else:
                res_flags.append('fail')
                writeResult(case_id, '', 'fail')
                writeBug(case_id, product_id, interface_name, new_url, results,
                         res_check)
            try:
                preOrderSN(results)
            except:
                print('ok')
        if method.upper() == "POST":
            headers = {'Authorization': '', 'Content-Type': 'application/json'}
            if "=" in urlParam(param):
                data = None
                print(
                    str(case_id) + ' request  is POST' +
                    new_url.encode('utf-8') + '?' +
                    urlParam(param).encode('utf-8'))
                results = requests.post(new_url + '?' + urlParam(param),
                                        data,
                                        headers=headers).text
                print('   response is POST' + results.encode('utf-8'))
                responses.append(results)
                res = readRes(results, '')
            else:
                print('request  is POST ' + new_url + '   body is ' +
                      urlParam(param))

                data = None
                req = urllib.request.Request(url=new_url,
                                             data=data,
                                             headers=headers,
                                             method="POST")
                try:
                    results = urllib.request.urlopen(req).read()
                    print('   response is POST ')
                    print(results)
                except Exception as e:
                    return caseWriteResult1(case_id, results, '0')
                res = readRes(results, res_check)
                print(res)
                if 'pass' == res:
                    res_flags.append('pass')
                    caseWriteResult1(case_id, results, '1')
                else:
                    res_flags.append('fail')
                    caseWriteResult1(case_id, results, '0')
                    writeBug(case_id, product_id, interface_name, new_url,
                             results, res_check)
            try:
                TaskId(results)
            except:
                print('ok1')


def seturl(set):
    '''
    描述：生成全局变量
    @set:string,全局变量配置
    '''
    global setvalue
    setvalue = '127.0.0.1'
    print('setvalue:', setvalue)
    info = list(Set.objects.filter(setname = set).values())
    print("info:", info)
    if len(info) == 1:
        setvalue = info[0]['setvalue']
    print("return  setvalue:", setvalue)
    return setvalue


def preOrderSN(results):
    global preOrderSN
    regx = '.*"preOrderSN":"(.*)","toHome"'
    pm = re.search(regx, results)
    if pm:
        preOrderSN = pm.group(1).encode('utf-8')
        return preOrderSN
    return False


def TaskId(results):
    global TaskId
    regx = '.*"TaskId":(.*),"PlanId"'
    pm = re.search(regx, results)
    if pm:
        TaskId = pm.group(1).encode('utf-8')
        #  print TaskId
        return TaskId
    return False


def taskno(param):
    global taskno
    a = int(time.time())
    taskno = 'task_' + str(a)
    return taskno


def writeResult(case_id, response, result):
    result = result.encode('utf-8')
    now = time.strftime("%Y-%m-%d %H:%M:%S")
    sql = "UPDATE apitest_apistep set apitest_apistep.apiresponse=%s,\
    apitest_apistep.apistatus=%s,\
    apitest_apistep.create_time=%s where apitest_apistep.id=%s;"

    param = (response, result, now, case_id)
    print('api autotest result is ' + result.decode())
    coon = pymysql.connect(user='root',
                           passwd='test123456',
                           db='autotest',
                           port=3306,
                           host='127.0.0.1',
                           charset='utf8')
    cursor = coon.cursor()
    cursor.execute(sql, param)
    coon.commit()
    cursor.close()
    coon.close()


def caseWriteResult(case_id, result):
    result = result.encode('utf-8')
    now = time.strftime("%Y-%m-%d %H:%M:%S")
    sql = "UPDATE apitest_apitest set apitest_apitest.apitestresult=%s,\
    apitest_apitest.create_time=%s where apitest_apitest.id=%s;"

    param = (result, now, case_id)
    print('api autotest result is ' + result.decode())
    coon = pymysql.connect(user='root',
                           passwd='test123456',
                           db='autotest',
                           port=3306,
                           host='127.0.0.1',
                           charset='utf8')
    cursor = coon.cursor()
    cursor.execute(sql, param)
    coon.commit()
    cursor.close()
    coon.close()
